package com.cwx.mychat;

import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOServer;
import com.cwx.mychat.websocket.NettyWebSocketStart;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


/**
 * 作者： cwx
 * 时间： 2024/9/20 16:44
 * 版本： 1.0
 * 注释：
 */
@Component("SocketApplication")
@Slf4j
public class SocketApplication implements ApplicationRunner {


    @Resource
    private NettyWebSocketStart nettyWebSocketStart;

    @Resource
    private SocketIOServer socketIOServer;

    @Override
    public void run(ApplicationArguments args) {
        nettyWebSocketStart.start();
        socketIOServer.start();
        log.info("服务启动了，可以开始开发了");
    }


    //启动socketIo服务
    @Async("threadPoolTaskExecutor")
    public void socketIoStart(){
        log.info("socketio服务启动中");
        //启动socketio服务
        Configuration configuration = new Configuration();
        configuration.setHostname("localhost");
        configuration.setPort(3000);
        configuration.setOrigin("*");

        final SocketIOServer server = new SocketIOServer(configuration);
        //监听连接事件
        server.addConnectListener(client -> {
            log.info("socket-io客户端连接成功");
            //向客户端发送消息
            client.sendEvent("connectionSuccess", "连接成功");
            client.sendEvent("connectionSuccess");
        });

        //监听加入房间事件
        server.addEventListener("joinRoom", String.class, (client, roomId, ackSender) -> {
            log.info("客户端加入房间:{}",roomId);
            client.joinRoom(roomId);
        });

        // 监听发送视频请求的事件
        server.addEventListener("callRemote", String.class, (socket, roomId, ackSender) -> {
            System.out.println("收到用户发送视频请求...");
            server.getRoomOperations(roomId).sendEvent("callRemote");
        });

        // 监听接受视频请求的事件
        server.addEventListener("acceptCall", String.class, (socket, roomId, ackSender) -> {
            server.getRoomOperations(roomId).sendEvent("acceptCall");
        });

        // 接收客户端的 offer
        server.addEventListener("clientSendOffer", OfferData.class, (socket, data, ackSender) -> {
            System.out.println("收到offer: " + data.offer + ", 房间ID: " + data.roomId);
            server.getRoomOperations(data.roomId).sendEvent("ServerSendOffer", data.offer);
        });

        // 接收客户端的 answer
        server.addEventListener("clientSendAnswer", AnswerData.class, (socket, data, ackSender) -> {
            System.out.println("收到answer: " + data.answer + ", 房间ID: " + data.roomId);
            server.getRoomOperations(data.roomId).sendEvent("ServerSendAnswer", data.answer);
        });

        // 接收客户端的 candidate
        server.addEventListener("clientSendCandidate", CandidateData.class, (socket, data, ackSender) -> {
            System.out.println("收到candidate: " + data.candidate + ", 房间ID: " + data.roomId);
            server.getRoomOperations(data.roomId).sendEvent("ServerSendCandidate", data.candidate);
        });

        // 接收客户端的挂断请求
        server.addEventListener("clientHangUp", HangUpData.class, (socket, data, ackSender) -> {
            System.out.println("收到挂断请求: " + data.roomId + ", 状态: " + data.status + ", 被叫: " + data.called);
            server.getRoomOperations(data.roomId).sendEvent("ServerHangUp", data.status, data.called);
        });


        // 启动服务器
        server.start();
        log.info("socket-io服务器启动成功...");

        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(server::stop));
    }

    // 数据类用于接收 offer、answer、candidate 和挂断请求
    public static class OfferData {
        public String offer;
        public String roomId;
    }

    public static class AnswerData {
        public String answer;
        public String roomId;
    }

    public static class CandidateData {
        public String candidate;
        public String roomId;
    }

    public static class HangUpData {
        public String roomId;
        public String status;
        public String called;
    }
}
